# Create your views here.

from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.http import HttpResponseRedirect
from django.contrib.auth import logout
from django.template import RequestContext
from market.marketData import MarketData
from market.strategyAndFundHelper import getPercOnAssetInStrat
from market.findNewRepRule2Ter import FindNewRepRule2TerHelper
from market.view import View
from market.math import isARepartition
from market.historyFactory import createHistory
from market.mathView import view2vec,  indexOfAssetInList
from market.models import BetRoom, Asset, Player
from market.models import Strategy, AssetPercentageInStrategy, Fund
from market.models import WebSiteComment
from market.jsonsForCharts import getComments
from market.jsonsForCharts import getPlayerInvestementRepartition
from market.killAssetHelper import killAssetWithConstantMtM, killAssetWithConstantNumbers
from django.core.mail import mail_admins, send_mail
from market import emailSettings
from market.cometHelper import getMarketPlacePlayerStatus, getChatRoomPlayerStatus
from market.stupidUserException import StupidUserException
from django.utils import simplejson

from django.db import transaction


###########################################################################################
# return the value associated to a name ( 0 if the name is not in the request ) and populate the status if no number is associated to the name
def getValueAssociatedToNameInRequest( request, name ):
        tmp = ""
        try:
                tmp = request.POST[name]
        except Exception:
                tmp =""
                
        res = -1
        if tmp == "":
                return 0

        try:
                return float(tmp)
        except Exception:
                raise StupidUserException('There is a problem with the value associated to %s' %name )

        
###########################################################################################
# implementation of rules 2 : the player change his strategy submitting a new one
# this is "part 2" where the new strategy is apply and the page with the new state returned
# "part 1" is implemented in the next function
def applyNewView( player, repartition ):
        player.setNewView( repartition )
        # update other player status
        for pdb in Player.objects.filter(mainStrategy__betroom = player.dbPlayer.mainStrategy.betroom):
                if pdb.userBeingThisPlayer.username != player.getName():
                        playerStatus = getMarketPlacePlayerStatus( pdb )
                        playerStatus.isUpToDateStatusForTheMarket = False
                        playerStatus.save()
        return 0

###########################################################################################
# implementation of rules 2 : the player change his strategy submitting a new one
# this is "part 1" where the new strategy is extract from the post request 
def SubmitNewRepartition0( request, player ):
        
        # string are un mutable so we cannot pass a strin for the status
        assets = Asset.objects.filter(isAvailableForStandardStrategy=True, betroom = player.dbPlayer.mainStrategy.betroom)
        
        # please note that the following check is also performed in the function setNewView of the PlayerData class.
        # However here we are raising a stupid user exception because we know for sure that the input are wrong
        tmp0 = [getValueAssociatedToNameInRequest( request, a.name) / 100 for a in assets]

        # test if the input rep is the set rep and return in case. this avoid useless calculation and dummy history
        isIdentique = True
        for a in range(len(assets)):
                if getPercOnAssetInStrat( player.dbPlayer.mainStrategy, assets[a] ) != tmp0[a]:
                        isIdentique = False
        if isIdentique:
                return 0

        
        # else we do the computation
        tmp = isARepartition(tmp0)
        if(  tmp[0] == False ):
                errorStr = " " + str(player.getName()) + " wants to submit: ["
                for i in range(len(tmp0)):
                        errorStr +=  "  %s " %tmp0[ i ]
                errorStr += "] and it is  not a repatition: "+ tmp[1]+ ". Nothing done!"
                raise StupidUserException( errorStr )

        repartition = [ [a, getValueAssociatedToNameInRequest( request, a.name)/ 100] for a in assets ]
        applyNewView( player, repartition )
        return 0


###########################################################################################
# implementation of rules 2Ter : the player change his strategy via selling a specified number of the specified asset
def sellAsset0( request, player ):
        # get the number of sold asset    
        numberOfSoldAsset0 = request.POST["numberSold"]
        numberOfSoldAsset = 0
        try:
                numberOfSoldAsset = float(numberOfSoldAsset0)
        except Exception:
                numberOfSoldAsset = -1

        m = MarketData(player.dbPlayer.mainStrategy.betroom)

        # get the index
        indexOfSoldAsset = indexOfAssetInList( request.POST["soldAsset"], m.assets)
        
        # some checks
        if numberOfSoldAsset < 0:
                raise StupidUserException( "Drat! What are you trying to do? Please set a positive number to sell. Nothing done!" )
        if numberOfSoldAsset == 0:
                raise StupidUserException( "Trying to sell 0 asset, I am sure you are not that poor! Nothing done!" )
        numberOfAssetHold = player.getMainFundTotalNumberOfAssets() * getPercOnAssetInStrat( player.dbPlayer.mainStrategy , m.assets[indexOfSoldAsset] ) 
        if numberOfSoldAsset > numberOfAssetHold:
                raise StupidUserException( "You cannot sell more assets than you have: check how many assets you have in the table!" )
        
        totalNumberOfAssetBefore = player.getMainFundTotalNumberOfAssets()
        indexOdBoughtAsset = indexOfAssetInList( request.POST["boughtAsset"], m.assets)
        if indexOfSoldAsset == indexOdBoughtAsset:
                raise StupidUserException( "Are you insane? The asset to sell and the asset to buy are the same. Nothing done!" )
        nPlayers =  len(Player.objects.filter(mainStrategy__betroom = player.dbPlayer.mainStrategy.betroom))
        marketPrices = view2vec( m.getMarketView(), m.assets)
        rb = [getPercOnAssetInStrat(player.dbPlayer.mainStrategy,a) for a in m.assets]
        newRepHelper = FindNewRepRule2TerHelper(
                totalNumberOfAssetBefore,
                rb,
                indexOfSoldAsset,
                numberOfSoldAsset,
                indexOdBoughtAsset,
                marketPrices,
                nPlayers
                )
        tmp = newRepHelper.findNewRepRule2Ter()
        v = View(m.assets, tmp[0])
        applyNewView( player, v.viewOnAssets )
        return 0
        
        
###########################################################################################
# return the page with the rules and the explanation
def SubmitNewStrategyMtMRep0(request, player):
        # string are un mutable so we cannot pass a strin for the status
        repartition = [ [s,getValueAssociatedToNameInRequest( request,s.name ) / 100] for s in Strategy.objects.filter(betroom=player.dbPlayer.mainStrategy.betroom)]

        # test if the input rep is the set rep and return in case. this avoid useless calculation and dummy history
        isIdentique = True
        for i in range(len(repartition)):
                fundList = Fund.objects.filter( strategy = repartition[i][0], player = player.dbPlayer )
                if len( fundList ) == 0:
                        currentPerc = 0
                else:
                        currentPerc = fundList[0].fundTargetPercentageInPortfolio
                if currentPerc != repartition[i][1] :
                        isIdentique = False
        if isIdentique:
                return 0
        
        # else we do the computation
        player.setNewStratMtMRep( repartition )
        return 0


###########################################################################################
# add the strategy to the invested strategy ansd set the percentage to 0
def addSelectedStratInTable0( request, player ):
        nameOfStratToAdd = name=request.POST['myStratDropList']
        stratToAdd = Strategy.objects.get( name = nameOfStratToAdd )
        fundAlreadyExist = False
        try:
                # if this succeed there is problem
                fund = Fund.objects.get( player = player.dbPlayer, strategy = stratToAdd )
                fundAlreadyExist = True
        except:#this is in fcat the normal behaviour
                fund = Fund(
                        strategy = stratToAdd,
                        player = player.dbPlayer,
                        fundTargetPercentageInPortfolio = 0,
                        numberOfAssetsInFund = 0
                        )
                fund.save()
               
        if fundAlreadyExist:
                raise StupidUserException("Add selected strat in table: trying to add an existing fund. Nothing done!")
        return HttpResponse( simplejson.dumps( [getPlayerInvestementRepartition(request)] ), mimetype='application/javascript')



###########################################################################################
# suppress the asset per strategy when they are useless
def removeUninvestedStratFromTable0( request, player ):
        # string are un mutable so we cannot pass a strin for the status
        for f in Fund.objects.filter( player = player.dbPlayer ):
                if f.fundTargetPercentageInPortfolio == 0:
                        f.delete()
        return HttpResponse( simplejson.dumps( [getPlayerInvestementRepartition(request)] ), mimetype='application/javascript')



################################################################################################################
# identification the pay dividend and kill asset at constant MtM
def killAssetInGloryMode0( request, player ):
        # get and check the asset name
        try:
                assetToKillName = request.POST["assetToKillName"]
                assetToKill = Asset.objects.get( name = assetToKillName, betroom = player.dbPlayer.mainStrategy.betroom )
        except Asset.DoesNotExist:
                raise StupidUserException('There is no asset called: ' +  assetToKillName + ". Nothing done!" )
        percentageOfTheMtMToPayOnTheBankAccount = 1.
        successStatus = killAssetWithConstantMtM( assetToKill, percentageOfTheMtMToPayOnTheBankAccount  )

        player.dbPlayer.mainStrategy.betroom.status = 2
        player.dbPlayer.mainStrategy.betroom.save()

        if successStatus == 1:
                m = MarketData(betroom=player.dbPlayer.mainStrategy.betroom)
                createHistory( m,[strat for strat in Strategy.objects.filter(betroom=player.dbPlayer.mainStrategy.betroom )], player.dbPlayer, "kills " +  assetToKillName )
                msg = player.getName() + " has deleted "+ assetToKillName+". Transactions have been suspended. You need to investigate and turn them on again"
        else:
                msg = 'Betroom ' + player.dbPlayer.mainStrategy.betroom.name + ' has been suspended because '  + player.getName() + ' has tried to delete ' + assetToKill.name + ' which is fully invested by every body. This probably means that the market should be ended.' 

        send_mail(
                'Celibax: ' + player.dbPlayer.mainStrategy.betroom.name + ' report',
                msg,
                emailSettings.SITE_HOST_EMAIL,
                [player.dbPlayer.mainStrategy.betroom.personInCharge.email],
                fail_silently=False)

        #end
        return HttpResponseRedirect("/strategies/")


        

